package com.zbkj.crmeb.marketing.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.CommonPage;
import com.common.PageParamRequest;
import com.crmeb.core.exception.CrmebException;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.utils.DateUtil;
import com.utils.PriceUtil;
import com.utils.vo.dateLimitUtilVo;
import com.zbkj.crmeb.chant.model.ChannelMerchant;
import com.zbkj.crmeb.enums.CouponUseStatusEnum;
import com.zbkj.crmeb.front.response.ConfirmOrderResponse;
import com.zbkj.crmeb.front.response.PriceGroupResponse;
import com.zbkj.crmeb.marketing.dao.StoreCouponDao;
import com.zbkj.crmeb.marketing.dao.StoreCouponUserDao;
import com.zbkj.crmeb.marketing.dto.CouponProductRangeDTO;
import com.zbkj.crmeb.marketing.model.StoreCoupon;
import com.zbkj.crmeb.marketing.model.StoreCouponUser;
import com.zbkj.crmeb.marketing.request.StoreCouponUserSearchRequest;
import com.zbkj.crmeb.marketing.response.StoreCouponUserResponse;
import com.zbkj.crmeb.marketing.service.StoreCouponUserService;
import com.zbkj.crmeb.store.dao.StoreOrderDao;
import com.zbkj.crmeb.store.model.StoreOrder;
import com.zbkj.crmeb.store.model.StoreProduct;
import com.zbkj.crmeb.store.model.StoreProductCoupon;
import com.zbkj.crmeb.store.response.StoreCartResponse;
import com.zbkj.crmeb.store.service.StoreProductCouponService;
import com.zbkj.crmeb.store.service.StoreProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class StoreCouponUserServiceImpl extends ServiceImpl<StoreCouponUserDao, StoreCouponUser> implements StoreCouponUserService {

    @Autowired
    StoreProductCouponService storeProductCouponService;
    @Autowired
    private StoreProductService storeProductService;
    @Autowired
    PriceUtil priceUtil;
    @Resource
    private StoreCouponDao storeCouponDao;
    @Resource
    private StoreOrderDao storeOrderDao;
    @Resource
    StoreCouponUserDao storeCouponUserDao;



    @Override
    public boolean use(StoreCouponUser storeCouponUser, ConfirmOrderResponse cor, ChannelMerchant channelMerchant, PriceGroupResponse orderPriceGroup) {
        List<Integer> productIdList = cor.getCartInfo().stream().filter(e->e.getChannelActivity() == null).map(StoreCartResponse::getProductId).distinct().collect(Collectors.toList());
        if(productIdList.size() < 1){
            throw new CrmebException("没有找到商品");
        }
        boolean flag = true;
        //可用优惠券商品id
        List<Integer> primaryKeyIdList = new ArrayList<>();
        switch (storeCouponUser.getUseType()){
            //全场通用
            case 1:
                primaryKeyIdList = productIdList;
                flag = false;
                break;
            //商品券
            case 2:
                List<StoreProductCoupon> list = storeProductCouponService.list(Wrappers.lambdaQuery(StoreProductCoupon.class).select(StoreProductCoupon::getProductId)
                        .eq(StoreProductCoupon::getIssueCouponId, storeCouponUser.getCouponId()).in(StoreProductCoupon::getProductId, productIdList));
                primaryKeyIdList = list.stream().map(StoreProductCoupon::getProductId).distinct().collect(Collectors.toList());
                if(CollectionUtils.isEmpty(primaryKeyIdList)){
                    throw new CrmebException("此优惠券为商品券，请购买相关商品之后再使用！");
                }
                break;
            //品类券
            case 3:
                List<StoreProduct> storeProductList = storeProductService.list(Wrappers.lambdaQuery(StoreProduct.class).eq(StoreProduct::getIsShow, 1).in(StoreProduct::getId, productIdList));
                CouponProductRangeDTO couponProductRangeDTO = JSONObject.parseObject(storeCouponUser.getPrimaryKey(), CouponProductRangeDTO.class);
                for (StoreProduct storeProduct : storeProductList) {
                    if(CollectionUtils.isNotEmpty(couponProductRangeDTO.getTempIds()) && !couponProductRangeDTO.getTempIds().contains(storeProduct.getTempId())){
                        continue;
                    }
                    if(CollectionUtils.isNotEmpty(couponProductRangeDTO.getBrandids()) && !couponProductRangeDTO.getBrandids().contains(storeProduct.getBrandId())){
                        continue;
                    }
                    if(CollectionUtils.isNotEmpty(couponProductRangeDTO.getCateIds()) && !couponProductRangeDTO.getCateIds().contains(storeProduct.getCateId())){
                        continue;
                    }
                    if(CollectionUtils.isNotEmpty(couponProductRangeDTO.getSeasons()) && !couponProductRangeDTO.getSeasons().contains(storeProduct.getSeasonCode())){
                        continue;
                    }
                    primaryKeyIdList.add(storeProduct.getId());
                }
                if(CollectionUtils.isEmpty(primaryKeyIdList)){
                    throw new CrmebException("此优惠券为品类券，请购买相关品类下的商品之后再使用！");
                }
                break;
            default:
                throw new CrmebException("此优惠券类型异常");
        }
        cor.setProductIdList(primaryKeyIdList);
        BigDecimal price;
        if(flag){
            List<StoreCartResponse> storeCartResponseList = cor.getCartInfo().stream().filter(e -> cor.getProductIdList().contains(e.getProductId())).collect(Collectors.toList());
            price = priceUtil.checkCouponPrice(storeCartResponseList, cor.getAddressInfo(), channelMerchant,storeCouponUser.getMinPrice());
        }else {
            price = orderPriceGroup.getTotalPrice();
            if(channelMerchant.getAppletType() == 1){
                price = price.add(orderPriceGroup.getStorePostage());
            }
            price = price.subtract(storeCouponUser.getMinPrice());
        }
        if(price.compareTo(BigDecimal.ZERO)<0){
            throw new CrmebException("金额小于优惠券最小使用金额");
        }
        return true;
    }

    /**
     * 优惠券用户
     * @param
     * @param pageParamRequest
     * @return
     */
    @Override
    public CommonPage<StoreCouponUserResponse> pageFrontCouponUsers(StoreCouponUserSearchRequest request, PageParamRequest pageParamRequest) {
        // 查询优惠券标识
        List<Integer> tagCouponIds = new ArrayList<>();
        if (StringUtils.isNotBlank(request.getTag())) {
            List<StoreCoupon> couponList = storeCouponDao.selectList(new LambdaQueryWrapper<StoreCoupon>()
                    .select(StoreCoupon::getTag, StoreCoupon::getId)
                    .like(StoreCoupon::getTag, request.getTag())
            );
            tagCouponIds = couponList.stream().map(StoreCoupon::getId).collect(Collectors.toList());
        }
        tagCouponIds.add(0);

        LambdaQueryWrapper<StoreCouponUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreCouponUser::getMerId, request.getMerId())
                .eq(Objects.nonNull(request.getUseType()), StoreCouponUser::getUseType, request.getUseType())
                .eq(Objects.nonNull(request.getCouponId()), StoreCouponUser::getCouponId, request.getCouponId())
                .in(StringUtils.isNotBlank(request.getTag()), StoreCouponUser::getCouponId, tagCouponIds)
                .like(StringUtils.isNotBlank(request.getUserNick()), StoreCouponUser::getUserNick, request.getUserNick())
                .like(StringUtils.isNotBlank(request.getName()), StoreCouponUser::getName, request.getName())
                .like(StringUtils.isNotBlank(request.getUserPhone()), StoreCouponUser::getUserPhone, request.getUserPhone());
        // 处理状态
        Date theDate = new Date();
        if (Objects.nonNull(request.getStatus())) {
            if (CouponUseStatusEnum.DISABLES.getCode().equals(request.getStatus())) {
                wrapper.ne(StoreCouponUser::getStatus, CouponUseStatusEnum.USED.getCode());
                wrapper.lt(StoreCouponUser::getEndTime, theDate);
            } else if (CouponUseStatusEnum.USABLE.getCode().equals(request.getStatus())) {
                wrapper.eq(StoreCouponUser::getStatus, CouponUseStatusEnum.USABLE.getCode());
                wrapper.gt(StoreCouponUser::getEndTime, theDate);
            } else {
                wrapper.eq(StoreCouponUser::getStatus, request.getStatus());
            }
        }

        // 时间
        if (StringUtils.isNotBlank(request.getDateLimit())) {
            dateLimitUtilVo dateLimitUtilVo = DateUtil.getDateLimit(request.getDateLimit());
            wrapper.between(StoreCouponUser::getCreateTime, dateLimitUtilVo.getStartTime(), dateLimitUtilVo.getEndTime());
        }
        if (StringUtils.isNotBlank(request.getUseDateLimit())) {
            dateLimitUtilVo useDateLimitUtilVo = DateUtil.getDateLimit(request.getUseDateLimit());
            wrapper.between(StoreCouponUser::getUseTime, useDateLimitUtilVo.getStartTime(),useDateLimitUtilVo.getEndTime());
        }
        wrapper.orderByDesc(StoreCouponUser::getId);

        Page<StoreCouponUser> page = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        List<StoreCouponUser> couponUserList = baseMapper.selectList(wrapper);

        // 处理返回参数
        List<Integer> couponIds = couponUserList.stream().map(StoreCouponUser::getCouponId).distinct().collect(Collectors.toList());
        List<StoreCoupon> storeCoupons = new ArrayList<>();
        // 查询标识
        if (CollectionUtils.isNotEmpty(couponIds)) {
            storeCoupons = storeCouponDao.selectList(new LambdaQueryWrapper<StoreCoupon>()
                    .select(StoreCoupon::getId, StoreCoupon::getTag)
                    .in(StoreCoupon::getId, couponIds));
        }
        Map<Integer, String> tagMap = storeCoupons.stream().collect(Collectors.toMap(StoreCoupon::getId, StoreCoupon::getTag));

        // 查询总单号
        List<Integer> usedCids = couponUserList.stream()
                .filter(c -> CouponUseStatusEnum.USED.getCode().equals(c.getStatus()) || CouponUseStatusEnum.USABLE.getCode().equals(c.getStatus()))
                .map(StoreCouponUser::getId)
                .collect(Collectors.toList());
        List<StoreOrder> orderList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(usedCids)) {
            orderList = storeOrderDao.selectList(new LambdaQueryWrapper<StoreOrder>()
                    .select(StoreOrder::getOrderId,StoreOrder::getCouponId)
//                    .eq(StoreOrder::getStatus, OrderStatusEnum.COMPLETE.getCode())
                    .in(StoreOrder::getCouponId, usedCids)
                    .eq(StoreOrder::getIsDel, 0)
            );
        }
        Map<Integer, String> orderIdMap = orderList.stream().collect(Collectors.toMap(StoreOrder::getCouponId, StoreOrder::getOrderId,(item1, item2) -> item1));

        List<StoreCouponUserResponse> responseList = new ArrayList<>();
        couponUserList.forEach(c -> {
            StoreCouponUserResponse response = new StoreCouponUserResponse();
            BeanUtils.copyProperties(c, response);
            response.setCouponNum(1);
            response.setUseStartTime(c.getStartTime());
            response.setUseEndTime(c.getEndTime());
            // 状态非实时更新
            if (CouponUseStatusEnum.USABLE.getCode().equals(c.getStatus()) && theDate.after(response.getUseEndTime())) {
                response.setStatus(CouponUseStatusEnum.DISABLES.getCode());
            }
            response.setTag(tagMap.get(c.getCouponId()));
            response.setOrderNo(orderIdMap.get(c.getId()));
            response.setNickname(c.getUserNick());
            responseList.add(response);
        });

        return CommonPage.restPage(CommonPage.copyPageInfo(page, responseList));
    }

    /**
     * 优惠券用户订单号列表
     * @param searchRequest
     * @param pageParamRequest
     * @return
     */
    @Override
    public List<StoreOrder> listCouponUserOrderIds(StoreCouponUserSearchRequest searchRequest, PageParamRequest pageParamRequest) {
        if (Objects.isNull(searchRequest.getId())) {
            throw new CrmebException("优惠券id不能为空");
        }
        StoreCouponUser storeCouponUser = baseMapper.selectById(searchRequest.getId());
        if (Objects.isNull(storeCouponUser)) {
            return new ArrayList<>();
        }
        // 查询总单号
        return storeOrderDao.selectList(new LambdaQueryWrapper<StoreOrder>()
                .select(StoreOrder::getOrderId,StoreOrder::getCouponId,StoreOrder::getCreateTime,StoreOrder::getId)
                .in(StoreOrder::getCouponId, storeCouponUser.getId())
                .eq(StoreOrder::getIsDel, 0)
                .orderByAsc(StoreOrder::getStatus)
        );
    }

    @Override
    public PageInfo<StoreCouponUserResponse> getList(StoreCouponUserSearchRequest scur, PageParamRequest pageParamRequest) {
        Page<Object> page = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        List<StoreCouponUser> storeCouponUsers = storeCouponUserDao.selectList(Wrappers.lambdaQuery(StoreCouponUser.class).eq(StoreCouponUser::getUid, scur.getUid())
                .eq(StoreCouponUser::getStatus, CouponUseStatusEnum.USABLE.getCode())
                .gt(StoreCouponUser::getEndTime, new Date()));
        List<StoreCouponUserResponse> storeCouponUserResponses = storeCouponUsers.stream().map(e -> {
            StoreCouponUserResponse response = new StoreCouponUserResponse();
            BeanUtils.copyProperties(e, response);
            return response;
        }).collect(Collectors.toList());
        return CommonPage.copyPageInfo(page, storeCouponUserResponses);
    }

    @Override
    public void rollbackByCancelOrder(StoreOrder storeOrder) {
        boolean update = this.update(Wrappers.lambdaUpdate(StoreCouponUser.class).eq(StoreCouponUser::getId, storeOrder.getCouponId())
                .set(StoreCouponUser::getStatus, 0).set(StoreCouponUser::getCid, 0).set(StoreCouponUser::getUseTime, null));
        if(!update){
            log.info("-----------优惠券返还失败,订单号:{},用户优惠券id:{}--------------",storeOrder.getId(),storeOrder.getCouponId());
        }
    }

}

